package com.monkeyboy.second.threadpool;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description 演示每个任务执行前后的钩子函数，暂停和恢复线程池的执行
 * @Author Gavin
 * @date 2020.04.28 11:01
 */
public class CanPauseableThreadPoolHook extends ThreadPoolExecutor {
    private boolean isPaused;
    //并发下修改boolean值保证其安全就上一把锁
    private final ReentrantLock lock = new ReentrantLock();
    private Condition unpaused = lock.newCondition();

    public CanPauseableThreadPoolHook(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    /**
     * @Description 重写钩子方法, 该方法每次执行任务之前都会被调用
     * @Param
     * @Date 2020.04.28 11:41
     **/
    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        lock.lock();
        try {
            while (isPaused) {//循环查看是否需要被暂停线程，如果暂停就会调用方法暂停线程池的任务继续运行
                unpaused.await();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    private void pause() {
        lock.lock();
        try {
            isPaused = true;
        }  finally {//记得要释放锁
            lock.unlock();
        }
    }

    private void resume() {//唤醒所有的任务线程继续执行
        lock.lock();
        try {
            isPaused = false;
            unpaused.signalAll();//该方法降唤醒任务线程继续执行
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        CanPauseableThreadPoolHook canPauseableThreadPoolHook = new CanPauseableThreadPoolHook(10, 20, 10L, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
        Runnable task = new Runnable() {
            @Override
            public void run() {
                System.out.println("我被执行");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        for (int i = 0; i < 10000; i++) {
            canPauseableThreadPoolHook.execute(task);
        }
        try {
            Thread.sleep(1500);
            System.out.println("任务暂停--------");
            canPauseableThreadPoolHook.pause();
            Thread.sleep(1500);
            System.out.println("任务继续----------");
            Thread.sleep(1000);
            canPauseableThreadPoolHook.resume();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}
